<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
  <link href="//gmpg.org/xfn/11" rel="profile">
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="generator" content="Hugo 0.68.3" />

  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>Python中的*args和**kwargs是什么？该如何使用？ &middot; 云淡风轻</title>

  
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/print.css" media="print">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/poole.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/syntax.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/hyde.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Abril+Fatface|PT+Sans:400,400i,700">


  
  <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
  <link rel="shortcut icon" href="/favicon.png">

  
  
</head>

  <body class=" ">
  <aside class="sidebar">
  <div class="container sidebar-sticky">
    <div class="sidebar-about">
      <a href="/my_technology_blog/"><h1>云淡风轻</h1></a>
      <p class="lead">
       这里是人凤的个人博客 
      </p>
    </div>

    <nav>
      <ul class="sidebar-nav">
        <li><a href="/my_technology_blog/">Home</a> </li>
        <li><a href="http://liu_ren_feng.gitee.io/my_technology_blog/tree/"> 个人简历 </a></li>
      </ul>
    </nav>

  </div>
</aside>

    <main class="content container">
    <div class="post">
  <h1>Python中的*args和**kwargs是什么？该如何使用？</h1>
  <time datetime=2018-04-08T08:29:30&#43;0800 class="post-date">Sun, Apr 8, 2018</time>
  <p><img src="../five/1.jpg" alt=""></p>
<p>在编程中，函数就是生命！</p>
<p>作为使用Python的新手——无论是编程新手，还是熟悉另一语言的人——都需要学习函数定义中的参数数目是否和想要传达的变元数目匹配。</p>
<p>这是基础性知识——有助于了解这个世界。</p>
<p>然而，接触到函数定义中的*args和**kwargs时，也会让新手刚开始就遇到心理障碍。</p>
<p>在Python中的代码中经常会见到这两个词 args 和 kwargs，前面通常还会加上一个或者两个星号。</p>
<p>别被这些语句所绊倒。其实这些并不是什么超级特殊的参数，也并不奇特，只是编程人员约定的变量名字，args 是 arguments 的缩写，表示位置参数；kwargs 是 keyword arguments 的缩写，表示关键字参数。</p>
<p>这其实就是 Python 中可变参数的两种形式，并且 *args 必须放在 **kwargs 的前面，因为位置参数在关键字参数的前面。</p>
<p>接下来，我们就具体学学如何使用它们。</p>
<h3 id="位置参数vs关键字参数">位置参数vs关键字参数</h3>
<p>为了学习什么是*args和**kwargs，我们需要区分两个概念。</p>
<p>首先，分清楚位置参数和关键字参数的区别。在最基本的函数中，做一个匹配游戏——参数1与参数1匹配，参数2与参数2匹配，诸如此类。</p>
<pre><code>def printThese(a,b,c):
   print(a, &quot;is stored in a&quot;)
   print(b, &quot;is stored in b&quot;)
   print(c, &quot;is stored inc&quot;)printThese(1,2,3)
&quot;&quot;&quot;
1 is stored in a
2 is stored in b
3 is stored in c
&quot;&quot;&quot;
</code></pre>
<p>三项参数都是必需的，缺了其中一个就会致错。</p>
<pre><code>def printThese(a,b,c):
   print(a, &quot;is stored in a&quot;)
   print(b, &quot;is stored in b&quot;)
   print(c, &quot;is stored inc&quot;)printThese(1,2)
&quot;&quot;&quot;
TypeError: printThese() missing 1 required positional argument:  c 
&quot;&quot;&quot;
</code></pre>
<p>为某函数定义中的参数给定默认值，该参数随后就会变为可选参数。</p>
<pre><code>def printThese(a,b,c=None):
   print(a, &quot;is stored in a&quot;)
   print(b, &quot;is stored in b&quot;)
   print(c, &quot;is stored inc&quot;)printThese(1,2)
&quot;&quot;&quot;
1 is stored in a
2 is stored in b
None is stored in c
&quot;&quot;&quot;
</code></pre>
<p>另外，这些可选参数也会成为可供选择的关键字，则此时可以规定函数调用参数名称并相应进行映射。</p>
<p>将三个变量默认值设为None，然后看看如何在不考虑顺序的情况下进行映射。</p>
<pre><code>defprintThese(a=None,b=None,c=None):
   print(a, &quot;is stored in a&quot;)
   print(b, &quot;is stored in b&quot;)
   print(c, &quot;is stored inc&quot;)printThese(c=3, a=1)
&quot;&quot;&quot;
def printThese(a=None,b=None,c=None):
   print(a, &quot;is stored in a&quot;)
   print(b, &quot;is stored in b&quot;)
   print(c, &quot;is stored inc&quot;)printThese(c=3, a=1)
&quot;&quot;&quot;
1 is stored in a
None is stored in b
3 is stored in c
&quot;&quot;&quot;
</code></pre>
<p>Splat运算符</p>
<p><img src="../five/2.jpg" alt=""></p>
<p>从开始说我爱该运算符的名称开始——太……可视化了。*常常与乘法运算有关，但是在Python中，则是splat运算符的两倍。</p>
<p>该运算符就像一个彩盒。笔者把延伸运算符——相当于splat的JavaScript——这个过程可以看做是打开一个多米诺骨牌，形成一个更大的序列，但是splat需要更有力的类比。</p>
<p>利用以下例子更容易解释清楚。</p>
<pre><code>a = [1,2,3]
b = [*a,4,5,6]print(b) # [1,2,3,4,5,6]
</code></pre>
<p>在代码实例中，将a的内容移入（解包）到新列表b中。</p>
<h3 id="如何使用args和kwargs">如何使用*args和**kwargs</h3>
<p>我们知道splat运算符解包多个值，并且知道函数参数有两种类型。若现在还未弄明白，那么可以将*args理解为变元的缩写，而**kwargs理解为关键字变元的缩写。</p>
<p>各参数用于解压其各自的变元类型，允许使用可变字长变元列表进行函数调用。例如，创建一个函数表示学生的考试分数。</p>
<pre><code>def printScores(student,*scores):
   print(f&quot;Student Name:{student}&quot;)
   for score in scores:
     print(score)printScores(&quot;Jonathan&quot;,100, 95, 88, 92, 99)
&quot;&quot;&quot;
Student Name: Jonathan
100
95
88
92
99
&quot;&quot;&quot;
</code></pre>
<p>噢，等等，我并未称呼其为<em>args？是的，“args”是一个标准化规范，但仍然只是一个名称。事实上，在</em>args中，唯一的星号是真正的参与者，创建了列表，其内容则是来自函数调用的位置参数（在这些定义变元后）。</p>
<p>这些理清楚之后，**kwargs就很容易理解了。名称并不重要，重要的是双星号创建了字典，其内容是关键字参数，来自函数调用（在这些定义变元后）。</p>
<p>为了更好地演示，我们创建一个函数，输出参加全国英语等级考试的人员名单。</p>
<pre><code>def printPetNames(owner,**pets):
   print(f&quot;Owner Name:{owner}&quot;)
   for pet,name in pets.items():
      print(f&quot;{pet}:{name}&quot;)printPetNames(&quot;Jonathan&quot;, dog=&quot;Brock&quot;,fish=[&quot;Larry&quot;, &quot;Curly&quot;, &quot;Moe&quot;],turtle=&quot;Shelldon&quot;)&quot;&quot;&quot;
Owner Name: Jonathan
dog: Brock
fish: [ Larry ,  Curly ,  Moe ]
turtle: Shelldon
&quot;&quot;&quot;
</code></pre>
<p><img src="../five/3.jpg" alt=""></p>
<p>最后，再给大家提供一些额外的“知识福利”。</p>
<p>下面一些谏言可有助于大家规避常见的陷阱并扩展知识面。</p>
<ul>
<li>
<p>利用*args和**</p>
</li>
<li>
<p>不能将**kwargs置于*args前，否则将产生错误；</p>
</li>
<li>
<p>清楚意识到关键字参数和<strong>kwargs之间的冲突，该值本是传达</strong>kwarg的意思，但是却不明就里的成为关键字参数的名称；</p>
</li>
<li>
<p>在函数调用时可以采用splat运算符。</p>
</li>
</ul>

</div>


    </main>

    
  </body>
</html>
